'use strict';

module.exports = (option, app) => {
    return async function (ctx, next) {
        
        // 建立数据
        let apiInfo = {
            ip: ctx.ip,
            method: ctx.method,
            apiName: '',
            url: '',
            body: null,
            state: '3',
            apiStatus: '',
            startAt: Date.now(),
            endAt: null
        }
        try {
            await next();
            apiInfo.state = '1';
        } catch (err) {
            // 所有的异常都在 app 上触发一个 error 事件，框架会记录一条错误日志
            console.log('请求出现错误：');
            console.log(err);
            app.emit('error', err, this);
            apiInfo.state = '0';
            const status = err.status || 500;
            // 生产环境时 500 错误的详细错误内容不返回给客户端，因为可能包含敏感信息
            status === 500 && app.config.env === 'prod' ? 'Internal Server Error' : err.message;

            // 从 error 对象上读出各个属性，设置到响应中
            ctx.body = {
                code: err.status,
                message: err.message
            };
            ctx.status = status;
            if (status === 422) {
                ctx.body.detail = err.errors;
            }
            apiInfo.body = ctx.body;
        }
        const addHistory = async () => {
            // 添加请求用户
            let auth = null;
            const token = ctx.header.token;
            try {
                await app.jwt.verify(token, app.config.jwt.secret);
                const { id } = await app.jwt.decode(token);
                auth = id;
            } catch{
                auth = null;
            }
            apiInfo.apiStatus = ctx.status.toString();
            apiInfo.auth = auth;
            apiInfo.url = ctx._matchedRoute;
            apiInfo.apiName = ctx.routerName;
            apiInfo.endAt = Date.now();
            // 增加一条请求记录
            ctx.service.history.create(apiInfo).then(res => {
                // console.log(res);
            }).catch(e => {
                console.error('接口请求记录增加失败', e);
            })
            // 接口访问次数+1 
            let apiName = ctx._matchedRoute.substring(5, ctx._matchedRoute.length);
            let routerIds = `${ctx.method}_${apiName}`;
            ctx.service.router.routerRequsetAdd(routerIds).then(res => {
                // console.log(res);
            }).catch(e => {
                console.error('接口访问次数增加失败', e);
            })
            // 计算请求耗时，控制台打印
            let timer = apiInfo.endAt - apiInfo.startAt;
            let stateObj = {
                '0': '失败',
                '1': '成功',
                '3': '未知',
            }
            console.log(`-- 接口<<${apiInfo.apiName}>>请求完成  请求结果：${stateObj[apiInfo.state]}  用时：${timer}ms --`);
            if (apiInfo.state === '0') {
                console.log(`失败原因：${ctx.body.message || ctx.body}`);
            }
        }

        if (ctx._matchedRoute && ctx._matchedRoute !== '/api/v1/history') {
            addHistory();
        }
    };
}
